package com.leyou.search.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.JsonUtils;
import com.leyou.common.vo.PageResult;
import com.leyou.item.clients.ItemClient;
import com.leyou.item.dto.*;
import com.leyou.search.pojo.Goods;
import com.leyou.search.repository.GoodsRepository;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class IndexService {

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private GoodsRepository goodsRepository;


    public void loadDataFromDataBase() {

        int page = 1;
        while (true) {
            //死循环，查询spu，不停的翻页
            PageResult<SpuDTO> spuDTOPageResult = this.itemClient.pageQuery(page, 50, null, null);
            page++;

            //当result为空的时候就没有查到，没查到说明查完了，可以结束了
            if (null == spuDTOPageResult) {
                break;
            }

            //获取返回结果中所有的spuDTO
            List<SpuDTO> items = spuDTOPageResult.getItems();


            //循环把spuDto转换为goods对象
            List<Goods> goods = items.stream().map(item -> buildGoods(item)).collect(Collectors.toList());


            //把封装好的goods集合保存到es中
            this.goodsRepository.saveAll(goods);
        }
    }

    //数据加工，把spuDTO，转为goods
    public Goods buildGoods(SpuDTO spuDTO) {
        //相同属性赋值
        Goods goods = BeanHelper.copyProperties(spuDTO, Goods.class);

        //categoryId
        goods.setCategoryId(spuDTO.getCid3());

        //createTime

        goods.setCreateTime(spuDTO.getCreateTime().getTime());

        //跨服务查询分类信息
        List<CategoryDTO> categoryDTOS = this.itemClient.queryCategoryByIds(spuDTO.getCategoryIds());

        //从分类对象集合中获取分类的名称，并拼接为字符串，以空格分隔
        String names = categoryDTOS.stream().map(CategoryDTO::getName).collect(Collectors.joining(" "));

        //TODO 写一个跨服务查询，根据分类查询品牌，把品牌名称拼接到all字段中


        //all 所有需要被搜索的信息，包含标题，分类，甚至品牌

        goods.setAll(spuDTO.getName() + names);

        //skus, id,title,price,image[0]

        //根据spuId跨服务查询sku
        List<SkuDTO> skuDTOS = this.itemClient.querySkuBySpu(spuDTO.getId());

        List<Map<String, Object>> skuMaps = new ArrayList<>();

        Set<Long> prices = new HashSet<>();

        //从sku中获取4个属性
        skuDTOS.forEach(skuDTO -> {
            Map<String, Object> skuMap = new HashMap<>();
            skuMap.put("id", skuDTO.getId());
            skuMap.put("title", skuDTO.getTitle());
            skuMap.put("price", skuDTO.getPrice());

            prices.add(skuDTO.getPrice());
            //
            skuMap.put("image", StringUtils.substringBefore(skuDTO.getImages(), ","));

            skuMaps.add(skuMap);
        });


        //处理好sku,保存
        goods.setSkus(JsonUtils.toString(skuMaps));

        //price
        goods.setPrice(prices);

        //specs,可搜索的规格参数的属性名称以及对应的值，key是规格参数名，值是，对应的参数值，参数值存在spuDetail中
        Map<String, Object> specs = new HashMap<>();

        //根据当前的分类，查询其对应的可搜索规格参数，

        //查询到当前分类下所有的可搜索规格参数
        List<SpecParamDTO> specParamDTOS = this.itemClient.queryParams(null, spuDTO.getCid3(), true);

        //跨服务查询spuDetail从中获取到存储的内容
        SpuDetailDTO spuDetailDTO = this.itemClient.querySpuDetailById(spuDTO.getId());

        //从spuDetail中取出通用json信息，并把其转换为map
        Map<Long, Object> genericMap = JsonUtils.nativeRead(spuDetailDTO.getGenericSpec(), new TypeReference<Map<Long, Object>>() {
        });

        //从spuDetail中获取特有规格属性可选值数组
        Map<Long, List<String>> specialMap = JsonUtils.nativeRead(spuDetailDTO.getSpecialSpec(),
                new TypeReference<Map<Long, List<String>>>() {
        });


        //循环把可搜索规格参数信息存储到specs中
        specParamDTOS.forEach(specParamDTO -> {
            //规格参数名称
            String specName = specParamDTO.getName();

            //规格参数的id，也就是通用map或者特有map的key
            Long id = specParamDTO.getId();

            Object value = null;

            //获取到对应规格参数的值,如果是通用规格
            if (specParamDTO.getGeneric()) {
                value = genericMap.get(id);
            } else {
                value = specialMap.get(id);
            }

            // 判断是否是数值类型
            if(specParamDTO.getNumeric()){
                // 是数字类型，分段
                value = chooseSegment(value, specParamDTO);
            }

            //key可搜索规格参数名称，value，其对应的规格参数值
            specs.put(specName, value);
        });

        goods.setSpecs(specs);

        return goods;
    }

    private String chooseSegment(Object value, SpecParamDTO p) {
        if (value == null || StringUtils.isBlank(value.toString())) {
            return "其它";
        }
        double val = parseDouble(value.toString());
        String result = "其它";
        // 保存数值段
        for (String segment : p.getSegments().split(",")) {
            String[] segs = segment.split("-");
            // 获取数值范围
            double begin = parseDouble(segs[0]);
            double end = Double.MAX_VALUE;
            if (segs.length == 2) {
                end = parseDouble(segs[1]);
            }
            // 判断是否在范围内
            if (val >= begin && val < end) {
                if (segs.length == 1) {
                    result = segs[0] + p.getUnit() + "以上";
                } else if (begin == 0) {
                    result = segs[1] + p.getUnit() + "以下";
                } else {
                    result = segment + p.getUnit();
                }
                break;
            }
        }
        return result;
    }

    private double parseDouble(String str) {
        try {
            return Double.parseDouble(str);
        } catch (Exception e) {
            return 0;
        }
    }

    public void createIndexes(Long spuId) {
        SpuDTO spuDTO = this.itemClient.querySpuById(spuId);

        Goods goods = this.buildGoods(spuDTO);

        this.goodsRepository.save(goods);

    }

    public void deleteIndexes(Long spuId) {
        this.goodsRepository.deleteById(spuId);
    }
}
